package com.zmn.oms.services.impl.orderencrypt;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.zmn.anole.dubbo.interfaces.AnoleRemoteService;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.oms.model.entity.entrust.EntrustOrder;
import com.zmn.oms.services.interfaces.orderencrypt.EntrustOrderEncryptService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * 类描述：
 *
 * @author LiangHailong
 * @date 2021/09/15 14:46
 */
@Service("entrustOrderEncryptService")
@Slf4j
public class EntrustOrderEncryptServiceImpl implements EntrustOrderEncryptService {

    // region 依赖
    @Reference(version = AnoleRemoteService.VERSION, check = false)
    private AnoleRemoteService anoleRemoteService;
    // endregion

    private static final String REG_PHONE = "^[\\d]+$";
    private static final String REG_ENCRYPTED_STR = "^[\\w/+=]+$";

    @Override
    public EntrustOrder encryptEntrustOrder(EntrustOrder entrustOrder) {
        if (entrustOrder == null) {
            return entrustOrder;
        }

        EntrustOrder entrustOrderCopy = BeanMapper.map(entrustOrder, EntrustOrder.class);

        Map<String, String> map = new HashMap<>();
        if (StringUtil.isNotBlank(entrustOrder.getUserPhone())
                && Pattern.matches(REG_PHONE, entrustOrder.getUserPhone())) {
            map.put("userPhone", entrustOrder.getUserPhone());
        }
        if (StringUtil.isNotBlank(entrustOrder.getMasterPhone())
                && Pattern.matches(REG_PHONE, entrustOrder.getMasterPhone())) {
            map.put("masterPhone", entrustOrder.getMasterPhone());
        }
        if (StringUtil.isNotBlank(entrustOrder.getAddress())
                && !Pattern.matches(REG_ENCRYPTED_STR, entrustOrder.getAddress())) {
            map.put("address", entrustOrder.getAddress());
        }

        if (!map.isEmpty()) {
            Map<String, String> encryptMulti = this.encryptMulti(map);
            if (encryptMulti == null) {
                return entrustOrderCopy;
            }

            String userPhone = encryptMulti.get("userPhone");
            if (StringUtil.isNotBlank(userPhone)) {
                entrustOrderCopy.setUserPhone(userPhone);
            }
            String masterPhone = encryptMulti.get("masterPhone");
            if (StringUtil.isNotBlank(masterPhone)) {
                entrustOrderCopy.setMasterPhone(masterPhone);
            }
            String address = encryptMulti.get("address");
            if (StringUtil.isNotBlank(address)) {
                entrustOrderCopy.setAddress(address);
            }
        }

        return entrustOrderCopy;
    }

    @Override
    public EntrustOrder decryptEntrustOrder(EntrustOrder entrustOrder) {
        if (entrustOrder == null) {
            return entrustOrder;
        }

        EntrustOrder entrustOrderCopy = BeanMapper.map(entrustOrder, EntrustOrder.class);

        Map<String, String> map = new HashMap<>();
        if (StringUtil.isNotBlank(entrustOrder.getUserPhone())
                && Pattern.matches(REG_ENCRYPTED_STR, entrustOrder.getUserPhone())) {
            map.put("userPhone", entrustOrder.getUserPhone());
        }
        if (StringUtil.isNotBlank(entrustOrder.getMasterPhone())
                && Pattern.matches(REG_ENCRYPTED_STR, entrustOrder.getMasterPhone())) {
            map.put("masterPhone", entrustOrder.getMasterPhone());
        }
        if (StringUtil.isNotBlank(entrustOrder.getAddress())
                && Pattern.matches(REG_ENCRYPTED_STR, entrustOrder.getAddress())) {
            map.put("address", entrustOrder.getAddress());
        }

        if (!map.isEmpty()) {
            Map<String, String> decryptMulti = this.decryptMulti(map);
            if (decryptMulti == null) {
                return entrustOrderCopy;
            }

            String userPhone = decryptMulti.get("userPhone");
            if (StringUtil.isNotBlank(userPhone)) {
                entrustOrderCopy.setUserPhone(userPhone);
            }
            String masterPhone = decryptMulti.get("masterPhone");
            if (StringUtil.isNotBlank(masterPhone)) {
                entrustOrderCopy.setUserPhone(masterPhone);
            }
            String address = decryptMulti.get("address");
            if (StringUtil.isNotBlank(address)) {
                entrustOrderCopy.setUserPhone(address);
            }
        }

        return entrustOrderCopy;
    }

    @Override
    public List<EntrustOrder> batchDecryptEntrustOrder(List<EntrustOrder> entrustOrders) {
        if (entrustOrders == null || entrustOrders.isEmpty()) {
            return entrustOrders;
        }

        List<EntrustOrder> entrustOrdersCopy = BeanMapper.mapList(entrustOrders, EntrustOrder.class);

        // 提取需要解密的手机号和身份证号
        Map<String, String> userPhoneMap = new HashMap<>(entrustOrders.size());
        Map<String, String> masterPhoneMap = new HashMap<>(entrustOrders.size());
        Map<String, String> addressMap = new HashMap<>(entrustOrders.size());
        for (int i=0,len=entrustOrdersCopy.size(); i<len; i++) {
            EntrustOrder item = entrustOrdersCopy.get(i);

            if (StringUtil.isNotBlank(item.getUserPhone())
                    && Pattern.matches(REG_PHONE, item.getUserPhone())) {
                userPhoneMap.put(String.valueOf(i), item.getUserPhone());
            }
            if (StringUtil.isNotBlank(item.getMasterPhone())
                    && Pattern.matches(REG_PHONE, item.getMasterPhone())) {
                masterPhoneMap.put(String.valueOf(i), item.getMasterPhone());
            }
            if (StringUtil.isNotBlank(item.getAddress())
                    && !Pattern.matches(REG_ENCRYPTED_STR, item.getAddress())) {
                addressMap.put(String.valueOf(i), item.getAddress());
            }
        }

        // 解密客户手机号
        if (!userPhoneMap.isEmpty()) {
            Map<String, String> decryptPhones = this.decryptMulti(userPhoneMap);
            if (decryptPhones != null) {
                decryptPhones.forEach((key, value) -> {
                    EntrustOrder entrustOrder = entrustOrdersCopy.get(Integer.parseInt(key));
                    if (entrustOrder != null && StringUtil.isNotBlank(value)) {
                        entrustOrder.setUserPhone(value);
                    }
                });
            }
        }
        // 解密师傅手机号
        if (!masterPhoneMap.isEmpty()) {
            Map<String, String> decryptPhones = this.decryptMulti(masterPhoneMap);
            if (decryptPhones != null) {
                decryptPhones.forEach((key, value) -> {
                    EntrustOrder entrustOrder = entrustOrdersCopy.get(Integer.parseInt(key));
                    if (entrustOrder != null && StringUtil.isNotBlank(value)) {
                        entrustOrder.setMasterPhone(value);
                    }
                });
            }
        }
        // 解密地址
        if (!addressMap.isEmpty()) {
            Map<String, String> decryptAddresses = this.decryptMulti(addressMap);
            if (decryptAddresses != null) {
                decryptAddresses.forEach((key, value) -> {
                    EntrustOrder entrustOrder = entrustOrdersCopy.get(Integer.parseInt(key));
                    if (entrustOrder != null && StringUtil.isNotBlank(value)) {
                        entrustOrder.setAddress(value);
                    }
                });
            }
        }

        return entrustOrdersCopy;
    }

    private Map<String, String> encryptMulti(Map<String, String> map) {
        ResponseDTO<Map<String, String>> encryptRemote = anoleRemoteService.batchEncryptMap(map);
        log.debug("anoleRemoteService#batchEncryptMap 入参[{}],出参[{}]",
                JSON.toJSONString(map), JSON.toJSONString(encryptRemote.getData())
        );
        if (encryptRemote.isSuccess()) {
            return encryptRemote.getData();
        } else {
            log.error("入参[{}],加密失败[{}]", JSON.toJSONString(map), encryptRemote.getMessage());
            return null;
        }
    }
    private Map<String, String> decryptMulti(Map<String, String> map) {
        ResponseDTO<Map<String, String>> encryptRemote = anoleRemoteService.batchDecryptMap(map);
        log.debug("anoleRemoteService#batchEncryptMap 入参[{}],出参[{}]",
                JSON.toJSONString(map), JSON.toJSONString(encryptRemote.getData())
        );
        if (encryptRemote.isSuccess()) {
            return encryptRemote.getData();
        } else {
            log.error("入参[{}],加密失败[{}]", JSON.toJSONString(map), encryptRemote.getMessage());
            return null;
        }
    }
}
